package cn.yangliu.nacos.comm.config.feign;

import java.lang.reflect.Type;
import java.util.Collections;

import cn.yangliu.nacos.comm.tools.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * The type O auth jackson encoder.
 *
 * @author 问道于盲
 */
public class FeignJacksonEncoder implements Encoder {
	/**
	 * current class's static member
	 * The constant LOGGER.
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(FeignJacksonEncoder.class);
	/**
	 * current class instance's member.
	 * The Mapper.
	 */
	private final ObjectMapper mapper;

	/**
	 * Instantiates a new O auth jackson encoder.
	 * allow any class to create a new instance.
	 */
	public FeignJacksonEncoder() {
		this(Collections.emptyList());
	}

	/**
	 * Instantiates a new O auth jackson encoder.
	 * allow any class to create a new instance.
	 *
	 * @param modules the modules
	 */
	public FeignJacksonEncoder(Iterable<Module> modules) {
		this(JsonUtils.getObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).registerModules(modules));
	}

	/**
	 * Instantiates a new O auth jackson encoder.
	 * allow any class to create a new instance.
	 *
	 * @param mapper the mapper
	 */
	public FeignJacksonEncoder(ObjectMapper mapper) {
		LOGGER.info("Using default jackson encoder!");
		this.mapper = mapper;
	}

	/**
	 * Encode.
	 *
	 * @param object   the object
	 * @param bodyType the body type
	 * @param template the template
	 */
	@SuppressWarnings("deprecation")
	@Override
	public void encode(Object object, Type bodyType, RequestTemplate template) {
		try {
			JavaType javaType = this.mapper.getTypeFactory().constructType(bodyType);
			template.body(this.mapper.writerFor(javaType).writeValueAsString(object));
		} catch (JsonProcessingException e) {
			throw new EncodeException(e.getMessage(), e);
		}
	}
}
